home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_12_03 / allison2 / romldr.c < prev    next >
Encoding:
Text File  |  1994-01-26  |  9.0 KB  |  318 lines

  1. Listing 1
  2. /* ROMLDR.C EXE locator program 
  3.    written by: Charles B. Allison
  4.    last change: 11-3-93 */
  5.  
  6. #include <sys\stat.h>
  7. #include <io.h>
  8. #include <dos.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <alloc.h>
  12. #include <conio.h>
  13. #include <ctype.h>
  14. #include <fcntl.h>
  15. #include <string.h>
  16. #define BC 1
  17. /* BC is Borland c, else assume Microsoft */
  18. typedef struct {
  19.     unsigned sig;   /* signature = 4d5ah */
  20.     unsigned lst_sec_lng; 
  21.         /*length of last sector in file modulo 512*/
  22.     unsigned file_size;  
  23.     /* size of file in 512 byte pages includes hdr*/
  24.     unsigned num_reloc;  
  25.                    /* number of relocation items */
  26.     unsigned hdr_siz;    
  27.             /* # of 16 byte paragraphs in header */
  28.     unsigned min_ld_para; 
  29.            /* min # of paragraphs above load file */
  30.     unsigned max_ld_para; 
  31.      /* max # of paragraphs requested by file */
  32.     unsigned disp_stack_seg; 
  33.            /* rel displacement of stack segment */
  34.     unsigned sp;            
  35.        /* contents of stack ptr on entry to prog */
  36.     unsigned chksm;     /* check sum for file */
  37.     unsigned ip;    /* beginning instruction ptr */
  38.     unsigned rel_cs_seg; /* relative cs segment */
  39.     unsigned off_reloc;  
  40.          /* offset to 1st relocation item typ. 1e */
  41.     unsigned over_lay;      /* overlay number */
  42.     unsigned rsrved;        /* ?? reserved ?? */
  43. /* relocation item format is seg:off location 
  44.   relative to the beginning of the code section */
  45.         } EXE_HDR;
  46. struct MP_TBL {
  47.   long addrs;       /* segment beg. address */
  48.   long haddrs;     /* segment high addrs*/
  49.   char class[12];       /* class of object */
  50.     } maptable[120];
  51.  
  52. void sort_table(void);
  53. void gethdr(char *bf);
  54. long hexcvt(char * num);
  55. size_t read_block(char far *segbuf,size_t segsz);
  56. long read_segm(int i);
  57. size_t write_block(char far *segbuf,size_t segsz);
  58. long write_segm(long segsize);
  59. int fix_segm(int i);
  60. int config(char *cfgfile);
  61. void term_error(int numerr);
  62.  
  63. unsigned (*ch_ptr)[2];/* pointer to translation table
  64.                [0] = offset,[1] = segment*/
  65. char mfile[14] = "rom.map"; /* dumy file names */
  66. char bfile[14] = "rom.bin";
  67. char efile[14] = "rom.exe";
  68. /*columns for starting and ending addresses in MAP */
  69. #define LCOL 1
  70. #define HCOL 8
  71. #ifdef BC
  72. #define MAPCOL 41;
  73. /*bc map file class column*/
  74. #else
  75. #define MAPCOL 45;
  76. /*ms map file class column */
  77. #endif
  78. int class_loc = MAPCOL;
  79. FILE *mapfile,*exefile,*binfile;
  80. #define BUF_SIZE 60
  81. char mapstring[BUF_SIZE];
  82. long fsize; /*number of bytes in exe file */
  83. int nsegs;  /* number of segments in map */
  84. unsigned romsadr = 0xf000,ramsadr=0x40;
  85. char header[10000];
  86. EXE_HDR *filhdr = (EXE_HDR *)header;
  87. char far *seg_buffer;
  88. int next_fix = 0;
  89. char ram_class[15] = "FAR_DATA";
  90. unsigned ramdata; /* beginning ram segment*/
  91. /* ************ main ************* */
  92. int main(int argc,char *argv[])
  93. {
  94. int r_class_flag=1,i;
  95. long tmp,ssize;
  96.  
  97. if((seg_buffer = (char far *) farmalloc(0x10000L))
  98.             == NULL) term_error(0);
  99. if(argc == 1) term_error(-1); /*any cfg file name? */
  100. config(argv[1]);
  101. i=0;
  102. while (fgets(mapstring,BUF_SIZE,mapfile))
  103.  {
  104. /* process map file from mapstring input */
  105. /* maptable[1] - n contains the segments -
  106. class STACK should be last one */
  107. /* ends with i having n+1 segments */
  108.   if( (int)strlen(mapstring) > class_loc+1)
  109.     {   /* get rid of \n at end of string */
  110.      mapstring[(int)strlen(mapstring)-1]='\0';
  111.      if((tmp = hexcvt(&mapstring[LCOL])) >= 0)
  112.        {
  113.     maptable[i].addrs = tmp;
  114.     maptable[i].haddrs=hexcvt(&mapstring[HCOL]);
  115.             &mapstring[class_loc]);
  116.         strcpy(maptable[i].class,
  117.                &mapstring[class_loc]);
  118.     if(r_class_flag)
  119.     if(strcmp(&mapstring[class_loc],ram_class)==0)
  120.       { /*set it to first class occurance*/
  121.        ramdata = (maptable[i].addrs) >>4;
  122.        r_class_flag = 0;
  123.       }
  124.     printf("\n Segment %4.4lx  Class  %s",
  125.     maptable[i].addrs/16,maptable[i].class);
  126.     i++;
  127.        }/* end - if hexcvt  */
  128.     } /* end if strlen */
  129.   if(i>=119) break;  /* error too many segments */
  130.  } /* end while */
  131. if(feof(mapfile))
  132.     printf("\nend of file\n");
  133.   else
  134.     printf("\nerror reading map file\n");
  135. nsegs = i-1; /* number of segments  [1 to nsegs] */
  136. gethdr(header); /* read in the exe header info */
  137. /* size of object section of file */
  138. fsize = (long) ((512L * (filhdr->file_size-1)) +
  139.     filhdr->lst_sec_lng - 16L * filhdr->hdr_siz);
  140. printf("\nStartup Address %4.4x:%4.4x\n",romsadr+
  141.               filhdr->rel_cs_seg,filhdr->ip);
  142. printf("Rom Size %lx\n",fsize);
  143. /* process the exe file header - sort fix ups */
  144. sort_table();
  145. /* read in exe file by segment
  146. do fixups from map table and
  147. write it to output file */
  148. for(i=0;i < nsegs;i++)
  149.    {
  150.     if((ssize = read_segm(i)) > 0L )
  151.        { /* ignore 0 length segments */
  152.     fix_segm(i);
  153.     write_segm(ssize );
  154.        }
  155.    }
  156. /* done - end the program */
  157. farfree(seg_buffer);
  158. fcloseall();
  159. return 0;
  160. }
  161. /* ****************** */
  162. /* qsort routine for far pointers */
  163. int cmp_ptr(const void *a, const void *b)
  164. {
  165. long vala,valb;
  166. vala=((long)((unsigned *)a)[0])+
  167.               (((unsigned *)a)[1]<<4);
  168. valb=((long)((unsigned *)b)[0])+
  169.               (((unsigned *)b)[1]<<4);
  170. vala -= valb;
  171. if(vala < 0) return -1;
  172. if(vala > 0) return 1;
  173. return 0;
  174. }
  175. /* ------ sort_table -------- */
  176. /* sort header table */
  177. void sort_table(void)
  178. {
  179.  qsort((void *)&header[filhdr->off_reloc],
  180.          filhdr->num_reloc,4,cmp_ptr);
  181. }
  182. /* ------- read_block -------- */
  183. size_t read_block(char far *segbuf,size_t segsz)
  184. {
  185. if(fread(segbuf,1,segsz,exefile) != segsz)
  186.        term_error(-7);
  187. return segsz;
  188. }
  189. /* ------- read_segm --------- */
  190. long read_segm(int i)
  191. {
  192. long segsize;
  193. segsize = maptable[i].haddrs - maptable[i].addrs;
  194. if(!segsize) return 0;
  195. segsize += maptable[i+1].addrs-(maptable[i].haddrs);
  196. if(segsize <= 0x8000)
  197.   { read_block(seg_buffer,(size_t)segsize);
  198.   } else {
  199.    read_block(seg_buffer,0x8000);
  200.    read_block((&seg_buffer[0x8000]),
  201.            (size_t)(segsize-0x8000));
  202.   }
  203. return segsize;
  204. }
  205. /* --------- write_block ---------- */
  206. size_t write_block(char far *segbuf,size_t segsz)
  207. {
  208. if(fwrite(segbuf,1,segsz,binfile) != segsz)
  209.     term_error(-8);
  210. return segsz;
  211. }
  212. /* -------- write_segm --------- */
  213. long write_segm(long segsize)
  214. {
  215. if(!segsize) return 0;
  216. if(segsize <= 0x8000)
  217.   {  write_block(seg_buffer,segsize);
  218.   } else {
  219.    write_block(seg_buffer,0x8000);
  220.    write_block((&seg_buffer[0x8000]),
  221.            (size_t)(segsize-0x8000));
  222.   }
  223. return segsize;
  224. }
  225. /* ------ fix_segm ------- */
  226. int fix_segm(int i)
  227. {
  228. unsigned tmp,cseg,fixup;
  229. unsigned far * fixptr;
  230. cseg = (unsigned)(maptable[i].addrs/16L);
  231. while(next_fix < filhdr->num_reloc)
  232.   {
  233.    if(ch_ptr[next_fix][1] > cseg) break;
  234.    tmp = ch_ptr[next_fix][0]; /*offset into buffer*/
  235.    fixptr = (unsigned far *) &seg_buffer[tmp];
  236.    fixup = *fixptr;
  237. /* modify segment fixup according to type */
  238.    if(fixup >= ramdata)
  239.      {/* modify for ram */
  240.       fixup -= ramdata;
  241.       fixup += ramsadr;
  242.      }
  243.      else
  244.      {/* handle as rom */
  245.       fixup += romsadr;
  246.      }
  247.    *fixptr = fixup;
  248.    next_fix++;
  249.   } /*end while */
  250. return 0 ;
  251. }
  252. /* -------- hexcvt ------- */
  253. /* do hex digits to unsigned long */
  254. long hexcvt(char * num)
  255. {
  256. char *term;
  257. long value;
  258. value = strtoul(num,&term,16);
  259. return value;
  260. }
  261. /* ------- gethdr -------- */
  262. void gethdr(char *buf )
  263. {
  264. int i,j=32; /*index counter */
  265.      if(fread(&buf[0],1,32,exefile) < 32)
  266.      term_error(-6);
  267. /* have filhdr contents so get size of full header */
  268. if(fread(&buf[j],16,filhdr->hdr_siz-2,exefile)
  269.         < filhdr->hdr_siz-2) term_error(-6);
  270. (unsigned *)ch_ptr =
  271.       (unsigned *)(&buf[filhdr->off_reloc]);
  272. /* get address of relocation table - ch_ptr [n][m]
  273.  m - 0 offset, 1 - seg, n relocation # */
  274. }
  275. /*----------- config -------------*/
  276. /* get configuration data */
  277. int config(char *cfgfile)
  278. {
  279. FILE *cfg;
  280. char buf[80]; 
  281. if((cfg = fopen(cfgfile,"r"))==NULL) term_error(-1);
  282. if(fgets(buf,80,cfg) == NULL) term_error(-2);
  283. if(sscanf(buf,"%s %s %s",&mfile,
  284.            &efile, &bfile) != 3) term_error(-2);
  285. /* Now try to open input file 1 */
  286. if((mapfile=fopen(mfile,"r"))==NULL)  term_error(-3);
  287. if((exefile=fopen(efile,"rb"))==NULL) term_error(-4);
  288. if((binfile=fopen(bfile,"wb"))==NULL) term_error(-5);
  289. if(fgets(buf,80,cfg) == NULL) term_error(-7);
  290. if(sscanf(buf,"%4x %4x",&romsadr,
  291.              &ramsadr) != 2) term_error(-7);
  292. if(fgets(buf,80,cfg) == NULL) term_error(-7);
  293. if(sscanf(buf,"%s",&ram_class) != 1) term_error(-7);
  294. return 0;
  295. }
  296. /* error handler */
  297. char *errlist[10] = {
  298.  "Memory Allocation Error",
  299.  "No configuration file, USAGE:romldr cfgfile.cfg",
  300.  "Configuration file error - File names",  //-2
  301.  "Map File open error",                    //-3
  302.  "Exe File open error",                    //-4
  303.  "Bin File open error",                    //-5
  304.  "Error reading header",               //-6
  305.  "Error reading exe file",               //-7
  306.  "Error writing bin file",           //-8
  307.  " "
  308.       };
  309. void term_error(int errnum)
  310. {
  311. errnum = abs(errnum);
  312. if(errnum >= 9) exit(-1);
  313. printf("%s\n",errlist[errnum]);
  314. farfree(seg_buffer);
  315. exit(errnum);
  316. }
  317.  
  318.